package com.white.commonlib.widget;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;

import com.white.commonlib.R;

/**
 * Created by ytf on 2016/10/19.
 */

public class CircleImageView extends AppCompatImageView
{

    private float borderWidthRatio = 0.05f;
    private Paint mBorderPaint;
    private Paint mBmpPaint;
    private Paint mShadowPaint;
    private float radius;
    private float borderWidth;
    private float shadowWidth;
    private Bitmap mSrcBmp;
    private float centerX;
    private float centerY;

    public CircleImageView(Context context)
    {
        super(context);
        init(null);
    }

    public CircleImageView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init(attrs);
    }

    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    private final int[] ATS = new int[]{android.R.attr.src};

    private void init(AttributeSet attrs)
    {
        if (attrs != null)
        {
            TypedArray a = getContext().obtainStyledAttributes(attrs, ATS);
            int srcId = a.getResourceId(0, -1);
            if (srcId != -1)
            {
                Drawable d = getContext().getResources().getDrawable(srcId);
                mSrcBmp = drawable2Bitmap(d);
            }
        }
        mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setColor(Color.WHITE);

        mBmpPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mShadowPaint.setStyle(Paint.Style.FILL);
    }

    public void setBorderColor(int color)
    {
        mBorderPaint.setColor(color);
    }

    public Bitmap drawable2Bitmap(Drawable drawable)
    {
        if (drawable == null)
            return null;
        if (drawable instanceof BitmapDrawable)
        {
            //转换成Bitmap
            return ((BitmapDrawable) drawable).getBitmap();
        } else
        {
            Bitmap bitmap = Bitmap.createBitmap(
                    drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(),
                    drawable.getOpacity() != PixelFormat.OPAQUE ?
                            Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight());
            drawable.draw(canvas);
            return bitmap;
        }
    }

    @Override
    public void setImageDrawable(Drawable drawable)
    {
        isBmpScaled = false;
        mSrcBmp = drawable2Bitmap(drawable);
        if (mSrcBmp != null)
        {
            calcBmpDimen();
        }
        invalidate();
    }

    @Override
    public void setImageBitmap(Bitmap bm)
    {
        isBmpScaled = false;
        mSrcBmp = bm;
        if (mSrcBmp != null)
        {
            calcBmpDimen();
        }
        invalidate();
    }

    @Override
    public void setImageResource(int resId)
    {
//        super.setImageResource(resId);
        isBmpScaled = false;
        mSrcBmp = BitmapFactory.decodeResource(getContext().getResources(), resId);
        if (mSrcBmp != null)
        {
            calcBmpDimen();
        }
        invalidate();
    }

    @Override
    protected void onDetachedFromWindow()
    {
        super.onDetachedFromWindow();
        if (mSrcBmp != null)
        {
            mSrcBmp = null;
//            mSrcBmp.recycle();
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);
        int width = getWidth();
        int height = getHeight();

        int i = Math.min(width, height);
        width = height = i;
        centerX = width / 2.0f;
        centerY = height / 2.0f;
        float temp = width / 2.0f;
        borderWidth = temp * borderWidthRatio;
        shadowWidth = borderWidth;
        if (allowDrawingStroke)
        {
            if (allowDrawingShadow)
            {
                radius = temp - borderWidth - shadowWidth;
            } else
            {
                radius = temp - borderWidth;
            }
        } else
        {
            radius = temp;
        }

        isBmpScaled = false;
        if (mSrcBmp != null)
        {
            calcBmpDimen();
        }
    }

    private boolean allowDrawingStroke = true;

    /***
     * 是否允许绘制边框， 默认允许
     */
    public void disallowStrokeDrawing()
    {
        allowDrawingStroke = false;
    }

    private boolean allowDrawingShadow;

    /***
     * 是否允许绘制阴影，默认允许，必须在允许绘制边框的前提下才可以绘制阴影
     */
    public void allowShadowDrawing()
    {
        allowDrawingShadow = true;
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        drawCircleImage(canvas);
        if (allowDrawingStroke)
        {
            drawShader(canvas);
        }
    }

    @Deprecated
    private void drawShadow(Canvas canvas)
    {
        Resources r = getContext().getResources();
        RadialGradient rg = new RadialGradient(centerX, centerY, centerX,
                new int[]{r.getColor(R.color.transparent), r.getColor(R.color.HalfBlack), r.getColor(R.color.transparent)},
                new float[]{0f, (radius + borderWidth) / centerX, 1.0f}, Shader.TileMode.CLAMP);
        Matrix matrix = new Matrix();
        matrix.setTranslate(0f, 5.0f);
        rg.setLocalMatrix(matrix);
        mShadowPaint.setShader(rg);
        canvas.drawCircle(centerX, centerY, centerX, mShadowPaint);
    }

    private void drawShader(Canvas canvas)
    {
        mBorderPaint.setStrokeWidth(borderWidth);
        if (allowDrawingShadow)
        {
            canvas.drawCircle(centerX, centerY, centerX - shadowWidth - borderWidth / 2.0f, mBorderPaint);
        } else
        {
            canvas.drawCircle(centerX, centerY, centerX - borderWidth / 2.0f, mBorderPaint);
        }
    }

    private void drawCircleImage(Canvas canvas)
    {
        if (mSrcBmp != null)
        {
            mBmpPaint.setShader(new BitmapShader(mSrcBmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
            if (allowDrawingStroke)
            {
                Matrix m = new Matrix();
                mBmpPaint.getShader().getLocalMatrix(m);
                m.postTranslate(borderWidth, borderWidth);
                mBmpPaint.getShader().setLocalMatrix(m);
            }
            canvas.drawCircle(centerX, centerY, radius, mBmpPaint);
        }
    }

    private boolean isBmpScaled;

    private void calcBmpDimen()
    {
        if (radius == 0 || isBmpScaled)
        {
            return;
        }
        Matrix matrix = new Matrix();
        int refDimen = Math.min(mSrcBmp.getWidth(), mSrcBmp.getHeight());
        float rate = radius * 2.0f / refDimen;
        if (rate != 1)
        {
//            matrix.preTranslate(borderWidth, borderWidth);
            matrix.setScale(rate, rate);
            mSrcBmp = Bitmap.createBitmap(mSrcBmp, 0, 0, refDimen, refDimen, matrix, true);
            isBmpScaled = true;
        }
    }
}
